unit uFormMain;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  uPluginIntf, StdCtrls, Dialogs, JvExStdCtrls, JvListBox,
  JvPlaylist, ComCtrls, ImgList,
  DrcpSvc, ExtCtrls, Menus;

  const RS_AUTO_START_FUNCTION_IDS='AUTO_START_FUNCTION_IDS';

type


  TForm_Main = class(TForm,IPluginable)
    TreeView1: TTreeView;
    ImageList2: TImageList;
    PopupMenu1: TPopupMenu;
    MenuItem_EnableAutoStart: TMenuItem;
    MenuItem_DisableAutoStart: TMenuItem;
    procedure FormDestroy(Sender: TObject);
    procedure Button_RefreshClick(Sender: TObject);
    procedure TreeView1DblClick(Sender: TObject);
    procedure MenuItem_EnableAutoStartClick(Sender: TObject);
    procedure MenuItem_DisableAutoStartClick(Sender: TObject);
  private
    FSoapAddr : string;
    FSoap : DrcpService;

    FUserId : string;

    FAutoStartFunctionIds : TStrings;
    { Private declarations }

    procedure ClearFunctionTree;
    //load tree
    procedure LoadChildrenNode(Tree : TTreeView;node : TTreeNode; AAllFuncs : TStrings; AFunctionId : string);
    procedure GetFuncChildren(AAllFuncs : TStrings; AParentId : String; VChildrenIds : TStrings);
    procedure ClearTreeView;
    procedure UpdateTreeView;

    procedure ClearListWithObject(AList : TStrings);
  protected
    FPlugin : IPlugin;
    procedure Init;
    procedure SetPlugin(APlugin : IPlugin);
    function GetPlugin:IPlugin;

    procedure LoadModule(AModule: Module; AFunction : Function_);
    procedure LoadFunction(AFunction : Function_);

  public
    { Public declarations }
    property Plugin : IPlugin read GetPlugin write SetPlugin;
  end;

var
  Form_Main: TForm_Main;
implementation

{$R *.dfm}

procedure TForm_Main.Init;
var
  lClientConfig : TStrings;
  lPrintPort : String;
  I : integer;
begin
  { TODO -oyou -cplugin-template : fill initialization code here }


  FUserId := Plugin.Variable[RS_USER_ID];

  //how to get soap address by context variable, see more RS_xxx by CTL + LeftClick
  FSoapAddr := Plugin.Variable[RS_DEFAULT_CONTAINER_SOAP_ADDR];
  FSoap := GetDrcpService(false,FSoapAddr);

  //how to get initialzation info
  //Plugin.InitString can be any string, strore in db [module.initstring]
  //how to get client-config
  lClientConfig := TStringList.Create;

  //lClientConfig.Text := Plugin.HostParams;
  lClientConfig.Text:= FSoap.ClientConfig_GetContent(FUserId+'_host',Plugin.Variable[RS_MODULE_ID]);

  FAutoStartFunctionIds := TStringList.Create;
  FAutoStartFunctionIds.Delimiter := ',';
  FAutoStartFunctionIds.DelimitedText := lClientConfig.Values[RS_AUTO_START_FUNCTION_IDS];

  lClientConfig.Free;

  ManualDock(Plugin.Container.GetPanel,nil,alNone);

  UpdateTreeView;



  //run the auto start modules
  for I := 0 to FAutoStartFunctionIds.Count -1 do
  begin
    if Fsoap.FunctionAuthorization_IsUserAuthorized(FUserId,FAutoStartFunctionIds[I]) then
      LoadFunction(FSoap.Function_Get(FAutoStartFunctionIds[I]));
  end;

end;

procedure TForm_Main.FormDestroy(Sender: TObject);
var
  lClientConfig : TStrings;
begin
  lClientConfig := TStringList.Create;
  lClientConfig.Values[RS_AUTO_START_FUNCTION_IDS] := FAutoStartFunctionIds.DelimitedText;

  FSoap.ClientConfig_SetContent(FUserId + '_host',Plugin.Variable[RS_MODULE_ID],lClientConfig.Text);

  lClientConfig.Free;

  { TODO -oyou -cplugin-template : fill finalization code here }

  FAutoStartFunctionIds.Free;
end;

procedure TForm_Main.Button_RefreshClick(Sender: TObject);
begin
  UpdateTreeView;
end;




procedure TForm_Main.ClearListWithObject(AList: TStrings);
var
  I : integer;
begin
  for I := 0 to AList.Count -1 do
    (AList.Objects[I]).Free;

  AList.Clear;
end;

procedure TForm_Main.ClearFunctionTree;
var
  i : integer;
  lfunc : Function_;
begin

  for i := 0 to TreeView1.Items.Count - 1 do
  begin
    lfunc := Function_(TreeView1.Items[i].Data);
    lfunc.Free;
  end;

  TreeView1.Items.Clear;

end;



procedure TForm_Main.TreeView1DblClick(Sender: TObject);
var
  lnode : TTreeNode;
  lfunc : Function_;
begin
  //run the function
//  ShowMessage('load-function');
  lnode := TreeView1.Selected;

  //==2 means not authorized
  if lnode.ImageIndex > 1 then
    Exit;

  lfunc := Function_(lnode.Data);

  if LowerCase(lfunc.typeId) = 'module' then
  begin
    LoadFunction(lfunc);
  end;
end;

procedure TForm_Main.LoadModule(AModule: Module; AFunction: Function_);
var
  lPluginClassName,
  lPluginName : string;
  lPlugin : IPlugin;
  lModuleVariables : TStrings;
  I : integer;

  lPluginMgr :  IPluginManager;
  lFunctionPath : string;
begin

  lPluginClassName := FSoap.Plugin_GetNameById(AModule.pluginId);
  lFunctionPath := FSoap.Function_GetPath(AFunction.id);

  lPluginMgr := Plugin.Container.PluginManager;

  if lPluginMgr.Plugins[lPluginClassName] <> nil then
  begin
    ShowMessage('error: plugin not found in pluginManager.');
    Exit;
  end;

  lPluginName := AModule.name + '_' + AModule.id;
  try
    //the second parameter here must be unqiue
    lPlugin := lPluginMgr.CreatePlugin(lPluginClassName, lPluginName);

    //module context from user define
    lModuleVariables := TStringList.Create;
    lModuleVariables.Text := AModule.param;
    for I := 0 to lModuleVariables.Count - 1 do
      lPlugin.Variable[lModuleVariables.Names[I]] := lModuleVariables.ValueFromIndex[I];
    lModuleVariables.Free;



    //module context dynamicly
    lPlugin.Variable[RS_MODULE_ID] := AModule.id;
    lPlugin.Variable[RS_MODULE_NAME] := AModule.name;
    lPlugin.Variable[RS_HOST_NAME]    := Plugin.Variable[RS_HOST_NAME];
    lPlugin.Variable[RS_FUNCTION_ID_OF_MODULE] := AFunction.id;
    lPlugin.Variable[RS_FUNCTION_PATH_OF_MODULE] := lFunctionPath;

    lPlugin.Init(Plugin.Container,AModule.initString);
    lPlugin.Execute;

    FSoap.Log_Add(Plugin.Variable[RS_USER_ID],Plugin.Variable[RS_HOST_NAME],'FCS client',0,'Admin','load module','module_id='+AModule.id);
  except
    on EPluginHadAlreadyLoaded do
    begin

      SendMessage( ClientHandle,
        WM_MDIACTIVATE,
        lPluginMgr.Plugins[lPluginName].GetHandle,
        0);

      //ShowMessage('module had been opened.');
    end;

    On E : Exception do
      ShowMessage('Load plugin fail:'+E.Message);
  end;

end;

procedure TForm_Main.LoadFunction(AFunction: Function_);
var
  lModule : Module;
begin

  lModule := FSoap.Module_GetByFunctionId(AFunction.id);

  if lModule <> nil then
    LoadModule(lModule, AFunction)
  else
    raise Exception.Create('Can not load module by function id.');

end;

procedure TForm_Main.ClearTreeView;
var
  i : integer;
  lfunc : Function_;
begin

  for i := 0 to TreeView1.Items.Count - 1 do
  begin
    lfunc := Function_(TreeView1.Items[i].Data);
    lfunc.Free;
  end;

  TreeView1.Items.Clear;

end;

procedure TForm_Main.GetFuncChildren(AAllFuncs: TStrings; AParentId: String;
  VChildrenIds: TStrings);
var
  I : integer;
  lFunc : Function_;
begin

  for I := 0 to AAllFuncs.Count - 1 do
  begin
    lFunc := Function_(AAllFuncs.Objects[I]);
    if lFunc.parentId = AParentId then
      VChildrenIds.AddObject(lFunc.id,lFunc);
  end;

end;

procedure TForm_Main.LoadChildrenNode(Tree: TTreeView; node: TTreeNode;
  AAllFuncs: TStrings; AFunctionId: string);
var
  lc,
  lfunc : Function_;
  lChildren : TStrings;
  i : integer;
  lcnode : TTreeNode;

  lNodeIsAuthorized : boolean;

  lOnlyLoadAuthorizedNode : boolean;

begin

  lOnlyLoadAuthorizedNode := false;

  lChildren := TStringList.Create;
  GetFuncChildren(AAllFuncs,AFunctionId,lChildren);

  for i := 0 to lChildren.Count -1 do
  begin
    lc := Function_(lChildren.Objects[I]);

    lNodeIsAuthorized := FSoap.FunctionAuthorization_IsUserAuthorized(FUserId,lc.id);
    if (not lOnlyLoadAuthorizedNode)
      or (lOnlyLoadAuthorizedNode and lNodeIsAuthorized) then
    begin

      lcnode:= Tree.Items.AddChildObject(node,lc.name,lc);

      if UpperCase(lc.typeId) = UpperCase('module') then
      begin

        if lNodeIsAuthorized then
        begin
          lcnode.ImageIndex := 1;
          lcnode.SelectedIndex := 1;
        end
        else
        begin
          lcnode.ImageIndex := 3;
          lcnode.SelectedIndex := 3;
        end;

      end
      else
      begin
        if lNodeIsAuthorized then
        begin
          lcnode.ImageIndex := 0;
          lcnode.SelectedIndex := 0;
        end
        else
        begin
          lcnode.ImageIndex := 2;
          lcnode.SelectedIndex := 2;
        end;

        LoadChildrenNode(Tree,lcnode, AAllFuncs,lc.id);
      end;

    end;

  end;

  lChildren.Free;

end;

procedure TForm_Main.UpdateTreeView;
var
  lfunc : Function_;
  lnode : TTreeNode;
  lAllFuncs : ArrayOf_tns2_Function;
  lFunctions : TStrings;
  I : integer;
begin
  ClearTreeView;

  if FUserId = '' then
    Exit;

  lAllFuncs := FSoap.Function_GetAll;
  //store to TStringList
  lFunctions := TStringList.Create;
  for I := 0 to Length(lAllFuncs) -1 do
  begin
    lFunc := lAllFuncs[I];
    lFunctions.AddObject(lFunc.id,lFunc);
  end;

  lfunc:=FSoap.Function_GetRoot();
  LoadChildrenNode(TreeView1,nil,lFunctions,lfunc.id);

  lFunctions.Free;

end;

function TForm_Main.GetPlugin: IPlugin;
begin
  Result := FPlugin;
end;

procedure TForm_Main.SetPlugin(APlugin: IPlugin);
begin
  FPlugin := APlugin;

  Init;

end;

procedure TForm_Main.MenuItem_EnableAutoStartClick(Sender: TObject);
var
  lMenuItem : TMenuItem;

  lnode : TTreeNode;
  lfunc : Function_;
begin
  lMenuItem := (Sender as TMenuItem);

  //run the function
  lnode := TreeView1.Selected;

  //==2 means not authorized
  if lnode.ImageIndex > 1 then
    Exit;

  lfunc := Function_(lnode.Data);

  if LowerCase(lfunc.typeId) = 'module' then
  begin
  //add this module to autostart list
    if Fsoap.FunctionAuthorization_IsUserAuthorized(FUserId,lfunc.id)
      and (FAutoStartFunctionIds.IndexOf(lfunc.id) < 0) then
    begin
      FAutoStartFunctionIds.Add(lfunc.id);
    end;
  end;
end;

procedure TForm_Main.MenuItem_DisableAutoStartClick(Sender: TObject);
var
  lMenuItem : TMenuItem;

  lnode : TTreeNode;
  lfunc : Function_;

  lIndex : integer;
begin
  lMenuItem := (Sender as TMenuItem);

  //run the function
//  ShowMessage('load-function');
  lnode := TreeView1.Selected;

  //==2 means not authorized
  if lnode.ImageIndex > 1 then
    Exit;

  lfunc := Function_(lnode.Data);

  if LowerCase(lfunc.typeId) = 'module' then
  begin
  //  ShowMessage('func name:'+lfunc.name);
  //add this module to autostart list

    lIndex := FAutoStartFunctionIds.IndexOf(lfunc.id);
    if lIndex >= 0 then
      FAutoStartFunctionIds.Delete(lIndex);
      
  end;

end;

end.

